#ifndef DependencyEncoder_H
#define DependencyEncoder_H
#include "DependencyPipe.h"
#include "ObjectReader.h"
#include "Parameters.h"
#include"common.h"

#define MINUS_LOG_EPSILON  50

// log(exp(x) + exp(y));
//    this can be used recursivly
// e.g., log(exp(log(exp(x) + exp(y))) + exp(z)) =
// log(exp (x) + exp(y) + exp(z))
inline double logsumexp(double x, double y, bool flg) {
  if (flg) return y;  // init mode
  const double vmin = _min(x, y);
  const double vmax = _max(x, y);
  if (vmax > vmin + MINUS_LOG_EPSILON) {
    return vmax;
  } else {
    return vmax + std::log(std::exp(vmin - vmax) + 1.0);
  }
}

class DependencyEncoder{
public:
	DependencyEncoder(int maxLength, DependencyPipe *pipe, char *trainforest, Parameters *param);
	virtual ~DependencyEncoder();
	virtual double gradient(long double *expected, int length);

protected:
	DependencyPipe *pipe;
	vector<vector<vector<double> > > probs;
	vector<vector<vector<vector<double> > > > nt_probs;
	ObjectReader* in;
	Parameters *param;

	virtual int getKey(int s, int t, int dir, int comp, int length);
	virtual double getZ(int length, double *beta);
	virtual void inside_outside(int length, double *beta, double *alpha);
	virtual void getExpected(long double *expected, double *beta, double *alpha, double z, int length);
	void updataExpected(long double *expected, int *keys, double m, int size);

};
#endif